package com.example.othree.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.othree.common.PageParam;
import com.example.othree.common.R;
import com.example.othree.entity.StationData;
import com.example.othree.entity.WeatherHistoryData;
import com.example.othree.entity.WheatCornGrowthYear;
import com.example.othree.service.WeatherHistoryDataService;
import com.example.othree.service.WheatCornGrowthYearService;
import com.example.othree.util.TianQinUtils;
import com.example.othree.util.TianQinUtils2;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.dao.DataAccessException;
import org.springframework.web.bind.annotation.*;

import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author zogran
 * @since 2024-11-12
 */
@RestController
@CrossOrigin
@RequestMapping("/api")
public class WeatherHistoryDataController {
    @Autowired
    private WeatherHistoryDataService weatherHistoryDataService;

    @Autowired
    private WheatCornGrowthYearService wheatCornGrowthService;


    @PostMapping("/weather/create")
    @ApiOperation("新增")
    public R create(@RequestBody WeatherHistoryData weatherHistoryData){
        return weatherHistoryDataService.save(weatherHistoryData) ? R.ok() : R.error();
    }

    @PostMapping("/weather/saveBatch")
    @ApiOperation("批量新增")
    public R saveBatch(@RequestBody List<WeatherHistoryData> weatherHistoryDataList){
        return weatherHistoryDataService.saveBatch(weatherHistoryDataList) ? R.ok() : R.error();
    }

    @GetMapping("/weather/list")
    public List<WeatherHistoryData> list(){
        return weatherHistoryDataService.list();
    }

    @PostMapping("/weather/update")
    @ApiOperation("修改")
    public R update(@RequestBody WeatherHistoryData weatherHistoryData){
        return weatherHistoryDataService.updateById(weatherHistoryData) ? R.ok() : R.error();
    }

    @PostMapping("/weather/delete/{id}")
    public R delete(@PathVariable Integer id){
        return weatherHistoryDataService.removeById(id) ? R.ok() : R.error();
    }

    @PostMapping("/weather/listPage")
    @ApiOperation("查询、分页")
    public R listPage(@RequestBody PageParam pageParam){
        HashMap param = pageParam.getParam();
        String station = param.get("station").toString();
        String date = param.get("date").toString();

        Page<WeatherHistoryData> page = new Page();
        page.setCurrent(pageParam.getPageNum());
        page.setSize(pageParam.getPageSize());

        LambdaQueryWrapper<WeatherHistoryData> lambdaQueryWrapper = new LambdaQueryWrapper();

        if(StringUtils.isNotBlank(station) && !"null".equals(station)){
            lambdaQueryWrapper.eq(WeatherHistoryData::getStation, station);
        }
        if(StringUtils.isNotBlank(date) && !"null".equals(date)){
            lambdaQueryWrapper.eq(WeatherHistoryData::getDate, date);
        }

        IPage result = weatherHistoryDataService.PageList(page, lambdaQueryWrapper);

        return R.ok().data("result", result);
    }



    @GetMapping("/weather-data-detail")
    @ApiOperation("获取农作物生长周期内气象要素详情【支持分页】")
    public R weatherlistByGrowthForPage(@RequestParam("city") String city,
                                                                  @RequestParam("district") String district,
                                                                  @RequestParam("year") String year,
                                                                  @RequestParam("crop") String crop,
                                                                  @RequestParam("startPeriod") String startPeriod, @RequestParam("endPeriod") String endPeriod,
                                                                  @RequestParam(value = "page", defaultValue = "1") int page,
                                                                  @RequestParam(value = "pageSize", defaultValue = "10") int pageSize){
        HashMap<String, Object> result = new HashMap<>();
        try {
            IPage<WeatherHistoryData> pageData = new Page();
            pageData.setSize(pageSize);
            pageData.setCurrent(page);
            weatherHistoryDataService.WeatherPageList(pageData, city, district, year, crop, startPeriod, endPeriod);


            result.put("total", pageData.getTotal());
            result.put("currentPage", pageData.getCurrent());
            result.put("pageSize", pageData.getSize());
            result.put("totalPages", pageData.getPages());

            HashMap<String, Object> data = new HashMap<>();
            data.put("city", city);
            data.put("district", district);
            for (WeatherHistoryData i:
                    pageData.getRecords()) {
                HashMap<String, Object> weatherData = new HashMap<>();
                weatherData.put("precipitation", i.getPrecipDay());
                weatherData.put("avgTemperature", i.getTempAvg());
                weatherData.put("surfaceTemperature", i.getSurfaceTempAvg());
                weatherData.put("humidity", i.getRhAvg());
                weatherData.put("sunshineHours", i.getSunshineDuration());
                weatherData.put("pressure", i.getPressureSite());
                weatherData.put("maxTemperature", i.getTempMax());
                weatherData.put("minTemperature", i.getTempMin());
                weatherData.put("windSpeed", i.getWindAvg());
                data.put(i.getDate(), weatherData);
            }

            result.put("data", data);
        }catch (DataAccessException e){
            e.printStackTrace();
            return R.error().message("数据库访问出错");
        } catch (Exception e){
            e.printStackTrace();
            return R.error().message("出现了未知错误");
        }


        return R.ok().data("data", result);
    }

    @GetMapping("/weather-data-detail_")
    @ApiOperation("获取农作物生长周期内气象要素详情【支持分页】")
    public R weatherlistByGrowthForPage_(@RequestParam("city") String city,
                                        @RequestParam("district") String district,
                                        @RequestParam("year") String year,
                                        @RequestParam("crop") String crop,
                                        @RequestParam("startPeriod") String startPeriod, @RequestParam("endPeriod") String endPeriod,
                                        @RequestParam(value = "page", defaultValue = "1") int page,
                                        @RequestParam(value = "pageSize", defaultValue = "10") int pageSize) {

        QueryWrapper<WheatCornGrowthYear> wrapper = new QueryWrapper<>();
        wrapper.eq("市", city);
        wrapper.eq("起始年份", "平均");
        wrapper.eq("作物", crop);

        WheatCornGrowthYear one = wheatCornGrowthService.getOne(wrapper);

        // 获取 Person 类的 "name" 属性值
        Field field = null;
        HashMap<String, Object> res = null;
        ArrayList<StationData> resList = null;
        try {
            field = WheatCornGrowthYear.class.getDeclaredField(startPeriod);
            field.setAccessible(true);

            // 获取属性值
            String startDate = (String) field.get(one);
            // 获取 "age" 属性值
            field = WheatCornGrowthYear.class.getDeclaredField(endPeriod);
            field.setAccessible(true);

            String endDate = (String) field.get(one);


            try {

                resList = new ArrayList<>();

                startDate = year + startDate.replace("-", "") + "000000";
                endDate = year + endDate.replace("-", "") + "000000";

                List<StationData> stationDataList = TianQinUtils2.getData(startDate, endDate);


                for (StationData stationData : stationDataList) {
                    if (stationData.getStationName().equals(district)) {
                        resList.add(stationData);
                    }
                }

                // 调用分页方法
                List<StationData> pagedList = getPagedList(resList, page, pageSize);

                // 内存里分页和按指定格式返回结果
                res = new HashMap<>();

                res.put("city", resList.get(0).getCity());
                res.put("district", resList.get(0).getCnty());
                TreeMap<String, StationData> stationMap = new TreeMap<>();
                for (StationData stationData : pagedList) {
                    SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd");
                    Date date = inputFormat.parse(stationData.getDatetime());
                    String outputDate = outputFormat.format(date);

                    stationMap.put(outputDate, stationData);
                }
                res.put("data", stationMap);


            } catch (Exception e) {
                e.printStackTrace();
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return R.ok().data("data", res).data("total", resList.size()).data("currentPage", page)
                .data("pageSize", pageSize).data("totalPages", (int) Math.ceil((double) resList.size() / pageSize));
    }

    @GetMapping("/weather-data-detail_-all")
    @ApiOperation("获取农作物生长周期内气象要素详情【支持分页】所有区县")
    public R weatherlistByGrowthForPage_All(@RequestParam("city") String city,
                                         @RequestParam("year") String year,
                                         @RequestParam("crop") String crop,
                                         @RequestParam("startPeriod") String startPeriod, @RequestParam("endPeriod") String endPeriod,
                                         @RequestParam(value = "page", defaultValue = "1") int page,
                                         @RequestParam(value = "pageSize", defaultValue = "10") int pageSize) {
        String[] timeRange = wheatCornGrowthService.getTimeRange(city, year, crop, startPeriod, endPeriod);
        String startDate = timeRange[0];
        String endDate = timeRange[1];

        ArrayList<StationData> res = new ArrayList<>();

        List<StationData> pagedList = null;
        try {

            startDate = startDate.replace("-", "") + "000000";
            endDate = endDate.replace("-", "") + "000000";

             List<StationData> stationDataList = TianQinUtils2.getData(startDate, endDate);


            // 获取指定市的所有区县呢

            for (StationData stationData : stationDataList) {
                if (stationData.getCity().contains(city)) {
                    res.add(stationData);
                }
            }

            // 内存里分页和按指定格式返回结果
            pagedList = getPagedList(res, page, pageSize);

        } catch (Exception e) {
            e.printStackTrace();
        }

        return R.ok().data("data", pagedList).data("total", res.size()).data("currentPage", page)
                .data("pageSize", pageSize).data("totalPages", (int) Math.ceil((double) res.size() / pageSize));
    }



    private List<StationData> getPagedList(ArrayList<StationData> resList, int page, int pageSize) {
        int totalSize = resList.size();
        // 计算起始索引和结束索引
        int startIndex = (page - 1) * pageSize;
        int endIndex = Math.min(startIndex + pageSize, totalSize);

        // 如果起始索引超出范围，返回空列表
        if (startIndex >= totalSize) {
            return new ArrayList<>();
        }

        // 使用 subList 提取分页数据
        return resList.subList(startIndex, endIndex);
    }


    @GetMapping("/weather-day-data")
    @ApiOperation("获取农作物生长周内逐日气象要素数据【不需要分页】")
    public R weatherListByGrowth(@RequestParam("city") String city,
                                        @RequestParam("district") String district,
                                        @RequestParam("year") String year,
                                        @RequestParam("crop") String crop,
                                        @RequestParam("startPeriod") String startPeriod, @RequestParam("endPeriod") String endPeriod){

        HashMap<String, Object> result = new HashMap<>();
        try {
            List<WeatherHistoryData> data = weatherHistoryDataService.WeatherList(city, district, year, crop, startPeriod, endPeriod);

            // 利用流操作从用户列表中提取数据，并构建HashMap
            result.put("precipitation", data.stream().map(WeatherHistoryData::getPrecipDay).toArray(Float[]::new));
            result.put("avgTemperature", data.stream().map(WeatherHistoryData::getTempAvg).toArray(Float[]::new));
            result.put("surfaceTemperature", data.stream().map(WeatherHistoryData::getSurfaceTempAvg).toArray(Float[]::new));
            result.put("humidity", data.stream().map(WeatherHistoryData::getRhAvg).toArray(Float[]::new));
            result.put("sunshineHours", data.stream().map(WeatherHistoryData::getSunshineDuration).toArray(Float[]::new));
            result.put("pressure", data.stream().map(WeatherHistoryData::getPressureSite).toArray(Float[]::new));
            result.put("maxTemperature", data.stream().map(WeatherHistoryData::getTempMax).toArray(Float[]::new));
            result.put("minTemperature", data.stream().map(WeatherHistoryData::getTempMin).toArray(Float[]::new));
            result.put("windSpeed", data.stream().map(WeatherHistoryData::getWindAvg).toArray(Float[]::new));


        }catch (DataAccessException e){
            e.printStackTrace();
            return R.error().message("数据库访问出错");
        } catch (Exception e){
            e.printStackTrace();
            return R.error().message("出现了未知错误");
        }


        return R.ok().data("data", result);
    }

//    @GetMapping("/weather-day-data_")
//    @ApiOperation("获取农作物生长周内逐日气象要素数据【不需要分页】")
//    public R weatherListByGrowth_(@RequestParam("city") String city,
//                                 @RequestParam("district") String district,
//                                 @RequestParam("year") String year,
//                                 @RequestParam("crop") String crop,
//                                 @RequestParam("startPeriod") String startPeriod, @RequestParam("endPeriod") String endPeriod){
//
//        QueryWrapper<WheatCornGrowthYear> wrapper = new QueryWrapper<>();
//        wrapper.eq("市", city);
////        wrapper.eq("县", district);
//        wrapper.eq("起始年份", "平均");
//        wrapper.eq("作物", crop);
//
//        WheatCornGrowthYear one = wheatCornGrowthService.list(wrapper).get(0);
//
//        Field field = null;
//        HashMap<String, Object> res = null;
//        try {
//            field = WheatCornGrowthYear.class.getDeclaredField(startPeriod);
//            field.setAccessible(true);
//
//            // 获取属性值
//            String startDate = (String) field.get(one);
//            // 获取 "age" 属性值
//            field = WheatCornGrowthYear.class.getDeclaredField(endPeriod);
//            field.setAccessible(true);
//
//            String endDate = (String) field.get(one);
//
//
//
//            // 解析json
//            try {
//
//                startDate = year + startDate.replace("-", "") + "000000";
//                endDate = year + endDate.replace("-", "") + "000000";
//
//                List<StationData> stationDataList = TianQinUtils2.getData(startDate, endDate);
//
//
//                // 打印解析后的数据
//                ArrayList<StationData> resList = new ArrayList<>();
//
//                System.out.println(stationDataList);
//                for (StationData stationData : stationDataList) {
//                    if (stationData.getCnty().contains(district)) {
//                        resList.add(stationData);
//                    }
//                }
//
//
//                // 内存里分页和按指定格式返回结果
//                res = new HashMap<>();
//                List<String> properties = Arrays.asList(
//                        "prsAvg", "prsMax", "prsMin", "temMax", "temAvg", "temMin",
//                        "rhuAvg", "rhuMin", "preTime2020", "preTime0808",
//                        "winS", "winS2miAvg", "gstAvg", "gstMax", "gstMin", "ssh"
//                );
//
//                for (String property : properties) {
//                    TreeMap<String, String> dataToValue = new TreeMap<>();
//                    for (StationData stationData : resList) {
//                        // 反射获取了又需要
//                        Field f = StationData.class.getDeclaredField(property);
//                        f.setAccessible(true);
//                        String value = (String) f.get(stationData);
//                        SimpleDateFormat in = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//                        SimpleDateFormat out = new SimpleDateFormat("yyyy-MM-dd");
//                        Date date = in.parse(stationData.getDatetime());
//                        String temp = out.format(date);
//                        dataToValue.put(temp, value);
//                    }
//                    res.put(property, dataToValue);
//                }
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//
//        } catch (Exception e) {
//            throw new RuntimeException(e);
//        }
//
//        return R.ok().data(res);
//    }

    @GetMapping("/weather-day-data_")
    @ApiOperation("获取农作物生长周内逐日气象要素数据【不需要分页】")
    public R weatherListByGrowth_(@RequestParam("city") String city,
                                  @RequestParam("district") String district,
                                  @RequestParam("year") String year,
                                  @RequestParam("crop") String crop,
                                  @RequestParam("startPeriod") String startPeriod,
                                  @RequestParam("endPeriod") String endPeriod){

        QueryWrapper<WheatCornGrowthYear> wrapper = new QueryWrapper<>();
        wrapper.eq("市", city);
        wrapper.eq("起始年份", "平均");
        wrapper.eq("作物", crop);

        List<WheatCornGrowthYear> growthList = wheatCornGrowthService.list(wrapper);
        if (growthList == null || growthList.isEmpty()) {
            return R.error().message("未找到对应的农作物生长数据");
        }

        WheatCornGrowthYear one = growthList.get(0);

        Field field = null;
        HashMap<String, Object> res = null;
        try {
            field = WheatCornGrowthYear.class.getDeclaredField(startPeriod);
            field.setAccessible(true);
            String startDate = (String) field.get(one);

            field = WheatCornGrowthYear.class.getDeclaredField(endPeriod);
            field.setAccessible(true);
            String endDate = (String) field.get(one);

            try {
                // 处理小麦跨年情况
                int startYear = Integer.parseInt(year);
                int endYear = startYear;

                // 如果是小麦，且开始时期在越冬前，结束时期在越冬后，则结束年份需要加1
                if ("小麦".equals(crop) && isBeforeWinter(startPeriod) && isAfterWinter(endPeriod)) {
                    endYear = startYear + 1;
                }

                startDate = startYear  + startDate.replace("-", "") + "000000";
                endDate = endYear + endDate.replace("-", "") + "000000";

                // 获取原始数据
                List<StationData> stationDataList = TianQinUtils2.getData(startDate, endDate);

                // 打印原始数据量
                System.out.println("原始数据量: " + stationDataList.size());

                // 处理数据：将异常值设为null
                ArrayList<StationData> resList = new ArrayList<>();
                for (StationData stationData : stationDataList) {
                    if (stationData.getCnty() != null && stationData.getCnty().contains(district)) {
                        // 清洗异常值
                        cleanStationData(stationData);
                        resList.add(stationData);
                    }
                }

                // 内存里分页和按指定格式返回结果
                res = new HashMap<>();
                List<String> properties = Arrays.asList(
                        "prsAvg", "prsMax", "prsMin", "temMax", "temAvg", "temMin",
                        "rhuAvg", "rhuMin", "preTime2020", "preTime0808",
                        "winS", "winS2miAvg", "gstAvg", "gstMax", "gstMin", "ssh"
                );

                for (String property : properties) {
                    TreeMap<String, String> dataToValue = new TreeMap<>();
                    for (StationData stationData : resList) {
                        Field f = StationData.class.getDeclaredField(property);
                        f.setAccessible(true);
                        String value = (String) f.get(stationData);

                        SimpleDateFormat in = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        SimpleDateFormat out = new SimpleDateFormat("yyyy-MM-dd");
                        Date date = in.parse(stationData.getDatetime());
                        String temp = out.format(date);
                        dataToValue.put(temp, value); // value可能为null
                    }
                    res.put(property, dataToValue);
                }
            } catch (Exception e) {
                e.printStackTrace();
                return R.error().message("数据处理异常: " + e.getMessage());
            }

        } catch (Exception e) {
            throw new RuntimeException("反射获取字段异常", e);
        }

        return R.ok().data(res);
    }

    // 判断是否为越冬前的时期
    private boolean isBeforeWinter(String period) {
        String[] beforeWinterPeriods = {"播种", "出苗", "分蘖","三叶", "越冬"};
        for (String p : beforeWinterPeriods) {
            if (p.equals(period)) {
                return true;
            }
        }
        return false;
    }

    // 判断是否为越冬后的时期
    private boolean isAfterWinter(String period) {
        String[] afterWinterPeriods = {"返青", "起身", "拨节", "孕穗", "抽穗", "开花", "乳熟", "成熟"};
        for (String p : afterWinterPeriods) {
            if (p.equals(period)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 清洗StationData对象中的异常值（将大于9999的值设为null）
     */
    private void cleanStationData(StationData data) {
        if (data == null) return;

        List<String> properties = Arrays.asList(
                "prsAvg", "prsMax", "prsMin", "temMax", "temAvg", "temMin",
                "rhuAvg", "rhuMin", "preTime2020", "preTime0808",
                "winS", "winS2miAvg", "gstAvg", "gstMax", "gstMin", "ssh"
        );

        for (String property : properties) {
            try {
                Field field = StationData.class.getDeclaredField(property);
                field.setAccessible(true);
                String value = (String) field.get(data);

                // 检查是否为异常值
                if (isInvalidValue(value)) {
                    field.set(data, null); // 将异常值设为null
                }
            } catch (Exception e) {
                // 忽略字段访问异常
            }
        }
    }

    /**
     * 检查单个值是否为异常值（大于9999）
     */
    private boolean isInvalidValue(String value) {
        if (value == null || value.trim().isEmpty()) {
            return false;
        }

        try {
            double numericValue = Double.parseDouble(value.trim());
            return numericValue > 9999.0;
        } catch (NumberFormatException e) {
            return false;
        }
    }

}

